#ifndef _THREAD_H_
#define _THREAD_H_

#include<iostream>
#include<string>
#include<pthread.h>
#include<cstdio>
#include<cstring>
#include<functional>

namespace ThreadModlue
{
	static uint32_t number = 1; // bug

	class Thread
	{
		using func_t = std::function<void()>;
	private:
		void EnableDetach()
		{
			std::cout << "线程被分离了" << std::endl;
			_isdetach = true;
		}
		void EnableRunning()
		{
			_isrunning = true;
		}
		// 类内成员函数，默认包含this指针，会导致调用pthread_create时
		// 因为多了一个this参数，导致参数不匹配，所以加一个static
		static void* Routine(void* args) 
		{
			Thread *self = static_cast<Thread*>(args);
			self->EnableRunning();
			if(self->_isdetach)
				self->Detach();
			pthread_setname_np(self->_tid, self->_name.c_str());
			self->_func();// 回调处理

			return nullptr;
		}
	public:
		Thread(func_t func)
			: _tid(0)
			, _isdetach(false)
			, _isrunning(false)
			, res(nullptr)
			, _func(func)
		{
			_name = "thread-" + std::to_string(number++);
		}

		void Detach()
		{	//1.防御性编程，避免重复执行分离操作
			if(_isdetach)
				return;
			//2.执行分离操作
			if(_isrunning)//将指定线程设置为分离状态，分离后的线程结束时，其资源会自动被系统回收，
						  //调用者无需再对其进行 pthread_join 操作 。
				pthread_detach(_tid);
			//3.设置分离标识：无论 pthread_detach 调用成功与否都会调用，以此更新线程的分离状态。
			EnableDetach();
		}

		bool Start()
		{
			if(_isrunning)
				return false;
			//因为Routine已经被static修饰了，所以需要传一个this
			int n = pthread_create(&_tid, nullptr, Routine, this);
			if(n != 0)//create失败了会返回错误码-》就是个大于0的数
			{						//将错误码转换为对应的错误信息字符串
				std::cerr << "create thread error: " << strerror(n) << std::endl;
				return false;
			}
			else
			{
				std::cout << _name << "create success" << std::endl;
				return true;
			}
		}

		bool Stop()
		{	//运行才能终止
			if(_isrunning)
			{
				int n = pthread_cancel(_tid);
				if(n != 0)
				{
					std::cerr << "create thread error: " << strerror(n) << std::endl;
					return false;
				}
				else
				{
					_isrunning = false;
					std::cout << _name << " stop" << std::endl;
					return true;
				}
			}
			return false;
		}

		void Join()
		{
			if(_isdetach)
			{
				std::cout << "你的线程已经是分离的了，不能进行join" << std::endl;
				return;
			}
			int n = pthread_join(_tid, &res);
			if(n != 0)
			{
				std::cerr << "create thread error: " << strerror(n) << std::endl;
			}
			else
			{
				std::cout << "join success" << std::endl;
			}
		}
		~Thread()
		{

		}

	private:
		pthread_t _tid;
		std::string _name;
		bool _isdetach;
		bool _isrunning;
		void* res;
		func_t _func;
	};
}

#endif